서울시 열린데이터 광장 데이터로 살펴본

서울시 구별 5대 강력범죄 연관요소 탐구

발단 : 대림, 구로 등 그분들이 많은 지역에는 이런 이미지가 박혀 있습니다


진짜 중국인/조선족 밀집 지역에서 범죄가 많이 일어날까?

서울시 구별 중국국적 외국인 수와 5대 범죄 발생건수 연관분석

  • 5대 강력범죄?
    • 살인, 강도, 강간및강제추행, 절도. 폭력
  • 사용한 데이터 (상세주소는 마지막 페이지 참고)
    • 서울시 5대 범죄 발생현황 통계 (구별) (2014~2018)
    • 서울시 등록외국인 현황 (국적별/구별) (2014~2018)
In [192]:
# 파일을 불러와서 데이터프레임 생성
foreigner_num_origin = pd.read_csv('서울시 외국인 주민(국적별) 통계 2013-2018.csv'
                                              ,encoding='CP949', skiprows=1, thousands=',')
foreigner_num_origin
Out[192]:
기간 구분 성별 합계 소계 중국 중국(한국계) 대만 일본 몽골 ... 캐나다 소계.4 러시아 러시아(한국계) 영국 기타.3 오세아니아 중남미 아프리카 기타.4
0 2013 합계 395640.0 303856.0 51179.0 225201.0 9847.0 12482.0 5147.0 ... NaN NaN 2,088 NaN NaN NaN NaN NaN NaN 24,783
1 2013 합계 남자 179261.0 134075.0 19632.0 102453.0 4989.0 4947.0 2054.0 ... NaN NaN 713 NaN NaN NaN NaN NaN NaN 13,902
2 2013 합계 여자 216379.0 169781.0 31547.0 122748.0 4858.0 7535.0 3093.0 ... NaN NaN 1,375 NaN NaN NaN NaN NaN NaN 10,881
3 2013 종로구 11880.0 7981.0 2584.0 4665.0 272.0 310.0 150.0 ... NaN NaN 62 NaN NaN NaN NaN NaN NaN 1,005
4 2013 종로구 남자 5342.0 3286.0 1042.0 1952.0 125.0 118.0 49.0 ... NaN NaN 24 NaN NaN NaN NaN NaN NaN 581
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
463 2018 강동구 6384.0 4570.0 652.0 3581.0 32.0 117.0 188.0 ... 159.0 76.0 29 8 18 21 77 17 17 ***
464 2018 강동구 남자 3034.0 2140.0 283.0 1761.0 12.0 11.0 73.0 ... 79.0 45.0 17 *** 13 12 45 10 9 ***
465 2018 강동구 여자 3350.0 2430.0 369.0 1820.0 20.0 106.0 115.0 ... 80.0 31.0 12 5 5 9 32 7 8 ***
466 2018 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
467 2018 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

468 rows × 44 columns

In [199]:
crime_most_five = pd.read_csv('서울시 5대 범죄 발생현황 2014-2018.csv'
                                              ,encoding='CP949', thousands=',')
crime_most_five
Out[199]:
기간 자치구 합계 합계.1 살인 살인.1 강도 강도.1 강간강제추행 강간강제추행.1 절도 절도.1 폭력 폭력.1
0 기간 자치구 발생 검거 발생 검거 발생 검거 발생 검거 발생 검거 발생 검거
1 2018 합계 101,948 74,487 143 139 143 151 6,412 6,046 39,175 19,762 56,075 48,389
2 2018 종로구 3,690 3,913 6 7 3 7 236 1,100 1,483 969 1,962 1,830
3 2018 중구 4,030 2,679 2 2 11 11 207 115 1,855 832 1,955 1,719
4 2018 용산구 3,411 2,543 1 1 3 2 331 285 1,096 522 1,980 1,733
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
126 2014 관악구 6,781 3,701 7 8 25 22 361 238 3,029 784 3,359 2,649
127 2014 서초구 5,558 3,122 6 9 14 12 285 184 2,747 782 2,506 2,135
128 2014 강남구 8,851 5,262 13 9 37 29 512 403 3,895 1,193 4,394 3,628
129 2014 송파구 8,004 3,982 9 8 9 10 255 195 4,199 885 3,532 2,884
130 2014 강동구 5,392 3,285 5 4 10 8 148 129 2,425 827 2,804 2,317

131 rows × 14 columns

In [213]:
# 처음엔 이런 걸 그렸습니다
# 직관적이지 못함, 의미 파악이 어려움
fig = px.scatter_3d(result2.reset_index(), x='기간', y='중국국적총합', z='5대범죄_발생총합건수',
              color='자치구', size_max=20, size='5대범죄_발생총합건수', width=800, height=800)
fig.show()
In [214]:
# Scattor plot의 모양새나, 연도별 변화를 봐도 두 변인 사이에 별 관계가 없어 보임
fig = px.scatter(result2.reset_index(), x='중국국적총합', y='5대범죄_발생총합건수',
              color='자치구', size_max=15, size='5대범죄_발생총합건수', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [215]:
fig = px.scatter(result2.reset_index(), x='중국국적총합', y='살인',
              color='자치구', size_max=15, size='살인', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [216]:
fig = px.scatter(result2.reset_index(), x='중국국적총합', y='강도',
              color='자치구', size_max=15, size='강도', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [217]:
fig = px.scatter(result2.reset_index(), x='중국국적총합', y='절도',
              color='자치구', size_max=15, size='절도', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [218]:
fig = px.scatter(result2.reset_index(), x='중국국적총합', y='강간강제추행',
              color='자치구', size_max=15, size='강간강제추행', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [219]:
fig = px.scatter(result2.reset_index(), x='중국국적총합', y='폭력',
              color='자치구', size_max=15, size='폭력', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [222]:
# 2018년 기준 각 요소들의 상관관계
for_corr2.corr(method='pearson')
Out[222]:
중국국적총합 5대범죄_발생총합건수 살인 강도 강간강제추행 절도 폭력
중국국적총합 1.000000 0.241903 0.557359 0.302846 0.118571 0.220225 0.260172
5대범죄_발생총합건수 0.241903 1.000000 0.594612 0.606587 0.801312 0.971584 0.974444
살인 0.557359 0.594612 1.000000 0.271016 0.469315 0.542147 0.607344
강도 0.302846 0.606587 0.271016 1.000000 0.496463 0.609513 0.569268
강간강제추행 0.118571 0.801312 0.469315 0.496463 1.000000 0.767011 0.717707
절도 0.220225 0.971584 0.542147 0.609513 0.767011 1.000000 0.902027
폭력 0.260172 0.974444 0.607344 0.569268 0.717707 0.902027 1.000000

중국인/조선족 인구수와 5대 강력범죄 발생 건수는 별 상관이 없다 (살인 제외)

  • 한계점 : '등록' 외국인 대상이기 때문에, 불법체류자의 영향은 알 수 없음
    • 구별 불법체류자 추정 수도 알 수 있으면, 더 좋은 분석이 될 수 있음
  • 살인의 경우, 영등포구라는 이상값을 제외하면 계수가 0.26이 나옴
    • 영등포구만 조심하는걸로...
    • 발표자는 영등포구 여의도동에 살고 있습니다...!?!?
In [223]:
# 영등포구를 제외한다면
for_corr.corr(method='pearson')
Out[223]:
중국국적총합 5대범죄_발생총합건수 살인 강도 강간강제추행 절도 폭력
중국국적총합 1.000000 0.063155 0.260940 0.268643 -0.033064 0.044569 0.090311
5대범죄_발생총합건수 0.063155 1.000000 0.541375 0.595181 0.789114 0.968766 0.971732
살인 0.260940 0.541375 1.000000 0.227909 0.431302 0.478686 0.560923
강도 0.268643 0.595181 0.227909 1.000000 0.479638 0.597801 0.555354
강간강제추행 -0.033064 0.789114 0.431302 0.479638 1.000000 0.751955 0.698744
절도 0.044569 0.968766 0.478686 0.597801 0.751955 1.000000 0.892135
폭력 0.090311 0.971732 0.560923 0.555354 0.698744 0.892135 1.000000

5대 강력범죄 발생건수와 상관계수가 높은 다른 요소도 있을까?

없는 데이터에서 최대한 쥐어 짜낸 결과를 보시겠습니다...


1. 구별 사회복지 예산액

2. 구별 지하철 역 갯수 (유동인구)

3. 서울 주민등록 전입지별 인구이동

1. 구별 사회복지 예산액

  • 사용한 데이터 (상세주소는 마지막 페이지 참고)
    • 서울시 5대 범죄 발생현황 통계 (구별) (2014~2018)
    • 서울시 1인당 사회복지 예산액 통계 (2014-2017)
In [231]:
result = welfare_budget_from2014.merge(crime_most_five_end2017, how='left')
result
Out[231]:
기간 자치구 금액(천원/명) 상대격차(배) 절대격차(천원/명) 합계 살인 강도 강간강제추행 절도 폭력
0 2014 종로구 608.0 1.22 109.8 5021 3 12 226 2272 2508
1 2014 중구 702.8 1.41 204.7 5231 6 13 221 2576 2415
2 2014 용산구 486.6 0.98 -11.5 3799 1 7 213 1560 2018
3 2014 성동구 495.6 0.99 -2.6 3582 1 5 141 1753 1682
4 2014 광진구 414.9 0.83 -83.2 6268 8 16 249 3167 2828
... ... ... ... ... ... ... ... ... ... ... ...
95 2017 관악구 621.7 0.93 -44.4 5525 8 7 379 1979 3152
96 2017 서초구 487.8 0.73 -178.3 4708 9 13 470 1812 2404
97 2017 강남구 537.6 0.81 -128.4 7720 7 20 607 3130 3956
98 2017 송파구 481.2 0.72 -184.8 5576 6 1 288 2274 3007
99 2017 강동구 666.6 1 0.6 4261 5 10 172 1645 2429

100 rows × 11 columns

In [232]:
fig = px.scatter(result, x='금액(천원/명)', y='합계',
              color='자치구', size_max=15, size='합계', width=600, height=600
                ,animation_frame='기간')
fig.show()
In [233]:
for_corr = result[result['기간']==2017][['금액(천원/명)', '합계']]
for_corr
Out[233]:
금액(천원/명) 합계
75 778.8 4057
76 905.0 4184
77 620.3 4060
78 620.7 2767
79 544.8 4646
80 754.6 3975
81 730.8 4571
82 695.6 3434
83 839.2 3393
84 716.9 1999
85 791.0 4209
86 761.7 3883
87 666.4 3113
88 668.8 5278
89 601.6 3882
90 716.9 5135
91 702.8 4895
92 870.1 3265
93 676.3 5969
94 632.3 3330
95 621.7 5525
96 487.8 4708
97 537.6 7720
98 481.2 5576
99 666.6 4261
In [234]:
# 0.4는 적어 보이지만, 사회과학에서는 유의미한 값으로 활용됨
for_corr.corr(method='pearson')
Out[234]:
금액(천원/명) 합계
금액(천원/명) 1.000000 -0.406691
합계 -0.406691 1.000000

1인당 사회복지 예산액과 5대 강력범죄 발생 건수는 음의 상관관계를 가짐

  • 한계점 : 상관계수의 절대값이 0.6만 되었어도 더 행복했을 것

2. 구별 지하철 역 개수

  • 사용한 데이터 (상세주소는 마지막 페이지 참고)
    • 서울시 5대 범죄 발생현황 통계 (구별) (2014~2018)
    • 서울시 자치구별 지하철역 수 (2019)
  • 지하철역이라구요?? : 유동인구와 관련되었을 것이라 추측
In [235]:
subway = pd.read_csv('서울 자치구별 전철역 수 - Sheet1.csv', encoding='utf-8')
subway
Out[235]:
자치구 전철역 수
0 강남구 29
1 중구 23
2 송파구 22
3 마포구 22
4 강서구 21
5 영등포구 19
6 성동구 19
7 서초구 19
8 용산구 18
9 노원구 18
10 동작구 17
11 은평구 15
12 종로구 15
13 중랑구 14
14 구로구 13
15 강동구 11
16 동대문구 11
17 광진구 11
18 성북구 9
19 도봉구 7
20 서대문구 7
21 양천구 6
22 금천구 4
23 관악구 4
24 강북구 3
In [236]:
merged = crime_most_five[crime_most_five['기간'] == 2018].merge(subway, how='left').drop(columns='기간')
merged
Out[236]:
자치구 합계 살인 강도 강간강제추행 절도 폭력 전철역 수
0 종로구 3690 6 3 236 1483 1962 15
1 중구 4030 2 11 207 1855 1955 23
2 용산구 3411 1 3 331 1096 1980 18
3 성동구 2457 2 5 126 999 1325 19
4 광진구 3915 7 2 229 1769 1908 11
5 동대문구 3680 2 5 145 1447 2081 11
6 중랑구 4288 4 3 174 1526 2581 14
7 성북구 3042 7 1 183 1164 1687 9
8 강북구 3437 8 7 188 1112 2122 3
9 도봉구 2249 1 5 113 781 1349 7
10 노원구 4007 5 5 194 1422 2381 18
11 은평구 3590 8 1 188 1278 2115 15
12 서대문구 2802 5 3 206 1062 1526 7
13 마포구 5172 6 6 473 2011 2676 22
14 양천구 3515 2 4 120 1384 2005 6
15 강서구 4629 11 6 269 1724 2619 21
16 구로구 4810 8 9 250 1717 2826 13
17 금천구 3293 6 7 200 1168 1912 4
18 영등포구 5840 17 8 391 2292 3132 19
19 동작구 3100 3 7 288 1151 1651 17
20 관악구 5026 9 10 352 2012 2643 4
21 서초구 4726 5 5 470 1851 2395 19
22 강남구 7513 10 14 600 3004 3885 29
23 송파구 5807 5 6 309 2352 3135 22
24 강동구 3919 3 7 170 1515 2224 11
In [237]:
fig = px.scatter(merged
                         ,x='전철역 수'
                         ,y='절도'
                         ,color='자치구'
                         ,size_max=15
                         ,size='절도'
                         ,width=600, height=600)
fig.show()
In [238]:
fig = px.scatter(merged, x='전철역 수', y='폭력'
                 ,color='자치구'
                 ,size_max=15
                 ,size='폭력'
                 ,width=600, height=600)
fig.show()
In [239]:
fig = px.scatter(merged, x='전철역 수', y='강간강제추행'
                 ,color='자치구'
                 ,size_max=15
                 ,size='강간강제추행'
                 ,width=600, height=600)
fig.show()
In [240]:
fig = px.scatter(merged, x='전철역 수', y='강도'
                 ,color='자치구'
                 ,size_max=15
                 ,size='강도'
                 ,width=600, height=600)
fig.show()
In [241]:
fig = px.scatter(merged, x='전철역 수', y='살인'
                 ,color='자치구'
                 ,size_max=15
                 ,size='살인'
                 ,width=600, height=600)
fig.show()
In [242]:
merged.corr(method='pearson')
Out[242]:
합계 살인 강도 강간강제추행 절도 폭력 전철역 수
합계 1.000000 0.594612 0.606587 0.801312 0.971584 0.974444 0.580999
살인 0.594612 1.000000 0.271016 0.469315 0.542147 0.607344 0.140307
강도 0.606587 0.271016 1.000000 0.496463 0.609513 0.569268 0.318223
강간강제추행 0.801312 0.469315 0.496463 1.000000 0.767011 0.717707 0.592739
절도 0.971584 0.542147 0.609513 0.767011 1.000000 0.902027 0.599340
폭력 0.974444 0.607344 0.569268 0.717707 0.902027 1.000000 0.512349
전철역 수 0.580999 0.140307 0.318223 0.592739 0.599340 0.512349 1.000000

구별 지하철 역 개수와 5대 강력범죄 중 절도, 폭력, 성범죄는 양의 상관관계를 가지고 있다

  • 유동인구가 많은 것이 원인으로 추측됨

3. 서울 주민등록 전입지별 인구이동

  • 사용한 데이터 (상세주소는 마지막 페이지 참고)
    • 서울시 5대 범죄 발생현황 통계 (구별) (2014~2018)
    • 서울시 주민등록 전입지별 인구이동 (2014-2018)
    • 주거지를 옮기는 사람의 수가 많으면, 지역 공동체가 형성되기 힘들며, 이는 곧 상호감시체계가 약함을 뜻함
In [404]:
result = moved_num.merge(crime_most_five, how='left')
result
Out[404]:
기간 자치구 이동한 인구 수 합계 살인 강도 강간강제추행 절도 폭력
0 2014 종로구 24191 5021 3 12 226 2272 2508
1 2014 중구 20105 5231 6 13 221 2576 2415
2 2014 용산구 35618 3799 1 7 213 1560 2018
3 2014 성동구 46521 3582 1 5 141 1753 1682
4 2014 광진구 56778 6268 8 16 249 3167 2828
... ... ... ... ... ... ... ... ... ...
120 2018 관악구 94403 5026 9 10 352 2012 2643
121 2018 서초구 74658 4726 5 5 470 1851 2395
122 2018 강남구 91611 7513 10 14 600 3004 3885
123 2018 송파구 101060 5807 5 6 309 2352 3135
124 2018 강동구 59334 3919 3 7 170 1515 2224

125 rows × 9 columns

In [548]:
for_corr3 = result[result['기간'] == 2018].loc[:, '이동한 인구 수':]
In [549]:
for_corr3.corr(method='pearson')
Out[549]:
이동한 인구 수 합계 살인 강도 강간강제추행 절도 폭력
이동한 인구 수 1.000000 0.626943 0.382918 0.244559 0.504526 0.594899 0.623106
합계 0.626943 1.000000 0.594612 0.606587 0.801312 0.971584 0.974444
살인 0.382918 0.594612 1.000000 0.271016 0.469315 0.542147 0.607344
강도 0.244559 0.606587 0.271016 1.000000 0.496463 0.609513 0.569268
강간강제추행 0.504526 0.801312 0.469315 0.496463 1.000000 0.767011 0.717707
절도 0.594899 0.971584 0.542147 0.609513 0.767011 1.000000 0.902027
폭력 0.623106 0.974444 0.607344 0.569268 0.717707 0.902027 1.000000

지도 위에 그려보기 : Interactive Map with Folium

Non-Interactive 지도를 쓰면 생기는 문제점


In [263]:
with open('시군구_위치데이터/seoul_municipalities_geo.json') as seoul_json:
    data = json.load(seoul_json)
In [545]:
interact(create_seoul_crime_map,
         crime_most_five=fixed(crime_most_five),
         crime_name=['살인', '강도', '절도', '폭력', '강간강제추행'],
         year=(2014, 2017, 1),
         color=['darkred', 'darkblue', 'purple', 'green'])
Out[545]:
<function __main__.create_seoul_crime_map(crime_most_five, crime_name, year, color)>

Bonus - 다중회귀모형

In [268]:
import statsmodels.api as sm
import statsmodels.formula.api as smf
In [271]:
# 다중선형회귀 적합
model = smf.ols(formula = '합계 ~ 인당복지예산 + 이사인구 + 지하철역수', data = for_modeling_rename)
result = model.fit()
result.summary()
Out[271]:
OLS Regression Results
Dep. Variable: 합계 R-squared: 0.517
Model: OLS Adj. R-squared: 0.502
Method: Least Squares F-statistic: 34.25
Date: Tue, 03 Dec 2019 Prob (F-statistic): 3.88e-15
Time: 19:05:32 Log-Likelihood: -820.92
No. Observations: 100 AIC: 1650.
Df Residuals: 96 BIC: 1660.
Df Model: 3
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
Intercept 3435.0732 790.867 4.343 0.000 1865.214 5004.932
인당복지예산 -1.8037 0.943 -1.913 0.059 -3.675 0.068
이사인구 0.0247 0.005 4.912 0.000 0.015 0.035
지하철역수 67.7401 14.117 4.798 0.000 39.717 95.763
Omnibus: 2.535 Durbin-Watson: 2.478
Prob(Omnibus): 0.282 Jarque-Bera (JB): 1.888
Skew: -0.161 Prob(JB): 0.389
Kurtosis: 2.409 Cond. No. 5.69e+05


Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 5.69e+05. This might indicate that there are
strong multicollinearity or other numerical problems.

결과

  • 회귀식 : y = 3435.0732 - 1.8037 인당복지예산 + 0.0247 이사인구 + 67.7401 * 지하철역수
  • 데이터의 질에 비하면 괜찮은 결정계수(R-squared) 값과 p-value가 나왔다.